package com.codi.bus.core.service.impl;

import com.codi.base.util.ListUtil;
import com.codi.base.util.MD5;
import com.codi.bus.core.domain.FundWarehouseTransfer;
import com.codi.bus.core.domain.User;
import com.codi.bus.core.fund.FundErrorConst;
import com.codi.bus.core.fund.dao.FundPortfolioTransferDao;
import com.codi.bus.core.fund.domain.FundPortfolioTransfer;
import com.codi.bus.core.fund.enums.FundPortfolioTransferStatusEnum;
import com.codi.bus.core.fund.request.PortfolioTransferRequestDto;
import com.codi.bus.core.fund.response.PortfolioTransferResult;
import com.codi.bus.core.resultModel.BaseResult;
import com.codi.bus.core.service.FundCombinationService;
import com.codi.bus.core.service.FundWarehouseTransferService;
import com.codi.bus.core.service.PortfolioTransferService;
import com.codi.bus.core.service.UserService;
import com.codi.bus.core.service.model.PortfolioQryModel;
import com.codi.bus.core.service.util.ModelPopulateUtils;
import com.codi.bus.core.vo.PortfolioTransferStatusVo;
import com.codi.fcloud.ufx.HsResponseUtil;
import com.codi.fcloud.ufx.constant.HSOutputParameterNames;
import com.codi.fcloud.ufx.constant.HsConst;
import com.codi.fcloud.ufx.hssale.query.AccountBankQuery;
import com.codi.message.constant.ErrorConst;
import com.codi.message.constant.ErrorConstant;
import com.codi.message.util.MessageUtil;
import com.codi.trade.dto.HsAccoBankQueryDto;
import com.codi.trade.dto.HsCombTransferTradeDto;
import com.codi.trade.enums.PortfolioTransferModeEnum;
import com.codi.trade.response.HsAccoBankQueryResponse;
import com.codi.trade.response.HsCombTransferTradeResponse;
import com.codi.trade.service.portfolio.HsCombTransferTradeService;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 模块名
 *
 * @author spy
 * @version 1.0 2018-01-30
 * @since 1.0
 */
@Slf4j
@Service
public class PortfolioTransferServceImpl implements PortfolioTransferService {

    @Autowired
    private HsCombTransferTradeService hsCombTransferTradeService;

    @Autowired
    private AccountBankQuery accountBankQuery;

    @Autowired
    private UserService userService;

    @Autowired
    private FundCombinationService fundCombinationService;

    @Autowired
    private FundWarehouseTransferService fundWarehouseTransferService;

    @Autowired
    private FundPortfolioTransferDao fundPortfolioTransferDao;
    @Autowired
    private LocaldataTradeOrderService localdataTradeOrderService;
    @Override
    @Transactional
    public PortfolioTransferResult transfer(PortfolioTransferRequestDto dto) {
        PortfolioTransferResult result = new PortfolioTransferResult();
        result.setSuccess(false);

        log.info("----------------transfer begin---------------------");

        User user = userService.getUser(dto.getUserId());

        if (Strings.isNullOrEmpty(user.getExternalClientId())) {

            result.setErrorCode(ErrorConstant.ERROR_NO_ACCOUNT);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConstant.ERROR_NO_ACCOUNT));
            return result;
        }

        //----- validate
        // tradeAcco
        HsAccoBankQueryDto accoBankQueryDto = HsAccoBankQueryDto.builder()
                                                                .client_id(user.getExternalClientId())
                                                                .trade_acco(dto.getPortfolioTradeAcco())
                                                                .build();
        List<HsAccoBankQueryResponse> hsAccoBanks = accountBankQuery.query(accoBankQueryDto);

        if (ListUtil.isEmpty(hsAccoBanks)) {
            result.setErrorCode(ErrorConst.TRADE_ACCOUNT_NOT_FUND);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConst.TRADE_ACCOUNT_NOT_FUND));
            return result;
        }
        HsAccoBankQueryResponse hsAccoBank = hsAccoBanks.get(0);
        // portfolioCode

        // 验证组合是否存在
        List<PortfolioQryModel> fundList = fundCombinationService.queryPorfolio(dto.getPortfolioCode());
        if (ListUtil.isEmpty(fundList)) {
            result.setErrorCode(ErrorConst.PORTFOLIO_IS_NOT_EXIST);
            result.setErrorMessage(MessageUtil.getErrorMsg(ErrorConst.PORTFOLIO_IS_NOT_EXIST, dto.getPortfolioCode()));
            return result;
        }

        PortfolioQryModel portfolioQryModel = fundList.get(0);
        String innerPortfolioCode = portfolioQryModel.getInnerCombcode();

        // transferId
        FundWarehouseTransfer fundWarehouseTransfer = fundWarehouseTransferService.selectOne(dto.getTransferId());
        if (fundWarehouseTransfer == null) {
            result.setErrorCode(FundErrorConst.PORTFOLIO_TRANSFER_NOT_EXIST);
            result.setErrorMessage(MessageUtil.getErrorMsg(FundErrorConst.PORTFOLIO_TRANSFER_NOT_EXIST));
            return result;
        }

        // validate exist relation
        //调仓中的记录条数
        Long inTransferCount = PageHelper.count(() -> {
            FundPortfolioTransfer record = FundPortfolioTransfer.builder()
                                                                .portfolioCode(dto.getPortfolioCode())
                                                                .innerPortfolioCode(innerPortfolioCode)
                                                                .transferId(dto.getTransferId())
                                                                .status(FundPortfolioTransferStatusEnum.APPLY_SUC.getKey())
                                                                .userId(dto.getUserId())
                                                                .build();
            fundPortfolioTransferDao.select(record);
        });
        if (inTransferCount > 0) {
            log.info("user has in transfer in this portfolio");
            result.setErrorCode(FundErrorConst.PORTFOLIO_TRANSFER_IN_THE_WAY);
            result.setErrorMessage(MessageUtil.getErrorMsg(FundErrorConst.PORTFOLIO_TRANSFER_IN_THE_WAY));
            return result;
        }

        //调仓成功的记录条数
        Long transferSucCount = PageHelper.count(() -> {
            FundPortfolioTransfer record = FundPortfolioTransfer.builder()
                                                                .portfolioCode(dto.getPortfolioCode())
                                                                .innerPortfolioCode(innerPortfolioCode)
                                                                .transferId(dto.getTransferId())
                                                                .userId(dto.getUserId())
                                                                .status(FundPortfolioTransferStatusEnum.SUCCESS.getKey())
                                                                .build();
            fundPortfolioTransferDao.select(record);
        });

        if (transferSucCount > 0) {
            log.info("user has transfer this portfolio");
            result.setErrorCode(FundErrorConst.PORTFOLIO_TRNASFER_SUC_IN_THIS_PERIOD);
            result.setErrorMessage(MessageUtil.getErrorMsg(FundErrorConst.PORTFOLIO_TRNASFER_SUC_IN_THIS_PERIOD));
            return result;
        }

        //----- submit
        HsCombTransferTradeDto transferTradeDto = HsCombTransferTradeDto.builder()
                                                                        .trade_acco(dto.getPortfolioTradeAcco())
                                                                        .password(MD5.MD5Encode(dto.getPassword()))
                                                                        .portfolio_code(dto.getPortfolioCode())
                                                                        .transfer_mode(PortfolioTransferModeEnum.NEW.getKey())
                                                                        .capital_mode(hsAccoBank.getCapital_mode())
                                                                        .detail_fund_way(hsAccoBank.getDetail_fund_way())
                                                                        .build();


        Map<String, Object> map = hsCombTransferTradeService.transfer(transferTradeDto);
        if (!HsResponseUtil.isOperationOk(map)) {
            String errorInfo = map.get(HSOutputParameterNames.ERROR_INFO).toString();
            String errorCode =  map.get(HSOutputParameterNames.ERROR_CODE).toString();
            result.setErrorCode(Integer.valueOf(errorCode));
            result.setErrorMessage(errorInfo);
            result.setSuccess(false);
            log.info("调仓失败");
            log.error("fail to transfer portfolio:{}", errorInfo);
            return result;
        }else {
            HsCombTransferTradeResponse transfer = ModelPopulateUtils.populateTransfer(map,new BaseResult());
            log.info("调仓成功");
            result.setAllotNo(transfer.getAllot_no());
            localdataTradeOrderService.addApplyOrder(dto.getUserId().intValue(), transfer.getAllot_no(), 1, "调仓", dto.getPortfolioTradeAcco(), user.getExternalClientId());
            // remember relation
            FundPortfolioTransfer record = FundPortfolioTransfer.builder()
                .userId(dto.getUserId())
                .portfolioCode(dto.getPortfolioCode())
                .innerPortfolioCode(innerPortfolioCode)
                .transferId(dto.getTransferId())
                .capitalMode(hsAccoBank.getCapital_mode())
                .detailFundWay(HsConst.DETAIL_FUND_WAY)
                .status(FundPortfolioTransferStatusEnum.APPLY_SUC.getKey())
                .transferMode(PortfolioTransferModeEnum.NEW.getKey())
                .allotNo(transfer.getAllot_no())
                .createDate(new Date())
                .build();
            fundPortfolioTransferDao.insertSelective(record);
        }




        log.info("--------------transfer end -----------------");

        result.setSuccess(true);
        return result;
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateTransferStatusSuc(PortfolioTransferStatusVo statusVo) {


        FundPortfolioTransfer portfolioTransfer = new FundPortfolioTransfer();
        portfolioTransfer.setId(statusVo.getId());
        portfolioTransfer.setStatus(FundPortfolioTransferStatusEnum.SUCCESS.getKey());

        if (statusVo.getConfirmDate() != null) {
            portfolioTransfer.setConfirmDate(statusVo.getConfirmDate());
        }

        fundPortfolioTransferDao.updateStatus(portfolioTransfer);


    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateTransferStatusFail(PortfolioTransferStatusVo statusVo) {
        FundPortfolioTransfer portfolioTransfer = new FundPortfolioTransfer();
        portfolioTransfer.setId(statusVo.getId());
        portfolioTransfer.setStatus(FundPortfolioTransferStatusEnum.FAIL.getKey());

        if (statusVo.getConfirmDate() != null) {
            portfolioTransfer.setConfirmDate(statusVo.getConfirmDate());
        }

        fundPortfolioTransferDao.updateStatus(portfolioTransfer);

    }
}
